/*
 * ModelCC, distributed under ModelCC Shared Software License, www.modelcc.org
 */

package org.modelcc.language.syntax;

import java.io.Serializable;

import org.modelcc.AssociativityType;
import org.modelcc.language.LanguageException;
import org.modelcc.language.metamodel.LanguageModel;

/**
 * Syntax specification factory.
 * 
 * @author Luis Quesada (lquesada@modelcc.org)
 */
public final class SyntaxSpecificationFactory implements Serializable 
{
    /**
     * Grammar factory.
     */
    private GrammarFactory gf;

    /**
     * Constraints factory.
     */
    private SyntaxConstraintsFactory cf;

    /**
     * Default constructor.
     */
    public SyntaxSpecificationFactory() 
    {
        gf = new GrammarFactory();
        cf = new SyntaxConstraintsFactory();
    }

    /**
     * Set an associativity constraint for an object type.
     * @param type the object type.
     * @param as the associativity constraint.
     */
    public void setAssociativity(Object type, AssociativityType as) 
    {
        cf.setAssociativity(type,as);
    }

    /**
     * Adds a composition precedence between rules.
     * @param ts1 the rule that precedes.
     * @param ts2 the rule that is preceded.
     */
    public void addCompositionPrecedence(Rule ts1,Rule ts2) 
    {
        cf.addCompositionPrecedences(ts1,ts2);
    }

    /**
     * Adds a start precedence between rules.
     * @param ts1 the rule that precedes.
     * @param ts2 the rule that is preceded.
     */
    public void addStartPrecedence(Rule ts1,Rule ts2) 
    {
        cf.addStartPrecedences(ts1,ts2);
    }

    /**
     * Removes a precedence relationship between tokens.
     * @param ts1 the token that precedes.
     * @param ts2 the token that is preceded.
     */
    public void removeCompositionPrecedence(Rule ts1,Rule ts2) 
    {
        cf.removeCompositionPrecedences(ts1,ts2);
    }

    /**
     * Adds an selection precedence between rules.
     * @param ts1 the rule that precedes.
     * @param ts2 the rule that is preceded.
     */
    public void addSelectionPrecedence(Rule ts1,Rule ts2) 
    {
        cf.addSelectionPrecedences(ts1, ts2);
    }

    /**
     * Removes an selection precedence between rules.
     * @param ts1 the rule that precedes.
     * @param ts2 the rule that is preceded.
     */
    public void removeSelectionPrecedences(Rule ts1,Rule ts2) 
    {
        cf.removeSelectionPrecedences(ts1, ts2);        
    }

    /**
     * Adds a rule.
     * @param r the rule to add.
     */
    public void addRule(Rule r) 
    {
        gf.addRule(r);
    }

    /**
     * Adds a not empty object.
     * @param r the not empty object to add
     */
    public void addNotEmpty(Object object) 
    {
        gf.addNotEmpty(object);
    }

    /**
     * Removes a rule.
     * @param r the rule to remove.
     */
    public void removeRule(Rule r) 
    {
        gf.removeRule(r);
    }


    /**
     * @param startType the start type to set
     */
    public void setStartType(Object startType) 
    {
        gf.setStartType(startType);
    }
    
    /**
     * @param sb the token symbol builder.
     */
    public void setTokenSymbolBuilder(SymbolBuilder sb) 
    {
        gf.setTokenSymbolBuilder(sb);
    }

    /**
     * Creates a syntax specification
     * @return Syntax specification
     * @throws LanguageException whenever a problem is detected (e.g. cyclic precedences or null elements)
     */
    public SyntaxSpecification create() 
    		throws LanguageException  
    {
        return create(null);
    }

    /**
     * Creates a syntax specification
     * @param model Language model
     * @return Syntax specification
     * @throws LanguageException whenever a problem is detected (e.g. cyclic precedences or null elements)
     */
    public SyntaxSpecification create(LanguageModel model) 
    		throws LanguageException  
    {
        return new SyntaxSpecification(gf.create(model),cf.create(model));
    }
}